#include "audio_element.h"
#include "audio_event_iface.h"
#include "audio_pipeline.h"
#include "board.h"
#include "es8388.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_vfs.h"
#include "fatfs_stream.h"
#include "filter_resample.h" // opus解码,adf没有提供接口配置采样率,所以需要resample
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "opus_decoder.h"
#include "opus_encoder.h"
#include "user_codec.h"

#define BAST_PATH "/littlefs"
static const char *TAG = "PCM_TO_OPUS";

FILE *f;
static int total_written;
static esp_err_t debug_open(audio_element_handle_t self) {
    ESP_LOGI(TAG, "Debug element opened");
    f = fopen("/littlefs/input.pcm", "wb");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open debug file for writing");
        return ESP_FAIL;
    }
    total_written = 0;

    es8388_read_all();
    return ESP_OK;
}

static esp_err_t debug_close(audio_element_handle_t self) {
    ESP_LOGI(TAG, "Debug element closed");
    if (f != NULL) {
        fclose(f);
        f = NULL;
    }
    return ESP_OK;
}

static int debug_process(audio_element_handle_t self, char *in_buffer, int in_len) {
    int r_size = audio_element_input(self, in_buffer, in_len);

    // if (!f) {
    //     ESP_LOGE(TAG, "Debug file not opened");
    //     return AEL_IO_DONE;
    // }

    // size_t written = fwrite(in_buffer, 1, r_size, f);
    // if (written != r_size) {
    //     ESP_LOGE(TAG, "Failed to write to debug file");
    //     return AEL_IO_DONE;
    // }
    // ESP_LOGI(TAG, "Wrote %d bytes to debug file", written);

    // total_written += written;
    // if (total_written >= 20 * 1024) {
    //     ESP_LOGI(TAG, "Debug file size limit reached, closing file");
    //     fclose(f);
    //     f = NULL;
    //     audio_element_report_status(self, AEL_STATUS_STATE_FINISHED);
    //     return AEL_IO_DONE;
    // }
    // ESP_LOG_BUFFER_HEX(TAG, in_buffer, (in_len > 12) ? 12 : in_len);
    
    // 继续运行
    // audio_element_report_status(self, AEL_STATUS_STATE_RUNNING);

    ESP_LOGI(TAG, "Read %d bytes", r_size);
    audio_element_update_byte_pos(self, r_size);

    return r_size;
}

static esp_err_t debug_destroy(audio_element_handle_t self) {
    ESP_LOGI(TAG, "Destroying debug element");
    return ESP_OK;
}

audio_element_handle_t debug_stream_init() {
    audio_element_cfg_t cfg = DEFAULT_AUDIO_ELEMENT_CONFIG();
    cfg.task_stack = 4 * 1024;
    cfg.open = debug_open;
    cfg.close = debug_close;
    cfg.process = debug_process;
    cfg.destroy = debug_destroy;
    cfg.buffer_len = 2048;
    cfg.tag = "debug";

    return audio_element_init(&cfg);
}

//
void opus_to_speaker_task(void *param) {
    ESP_LOGI(TAG, "Opus decoding task started on core %d", xPortGetCoreID());

    // 1. 初始化管道
    audio_pipeline_handle_t pipeline;
    audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    pipeline = audio_pipeline_init(&pipeline_cfg);
    if (!pipeline) {
        ESP_LOGE(TAG, "Failed to create audio pipeline");
        vTaskDelete(NULL);
        return;
    }

    // 2. 创建 FATFS 读取流
    audio_element_handle_t fatfs_reader = fatfs_stream_init(
        &(fatfs_stream_cfg_t){.type = AUDIO_STREAM_READER, .task_stack = 4096, .task_prio = 4, .task_core = 1, .ext_stack = true});

    // 3. 创建 Opus 解码器
    opus_decoder_cfg_t opus_dec_cfg = DEFAULT_OPUS_DECODER_CONFIG();
    audio_element_handle_t opus_decoder = decoder_opus_init(&opus_dec_cfg);

    // 在解码后添加 `resample`
    rsp_filter_cfg_t rsp_cfg = DEFAULT_RESAMPLE_FILTER_CONFIG();
    rsp_cfg.src_rate = 48000;  // 由于 Opus 可能默认解码成 48kHz
    rsp_cfg.src_ch = 1;        // 单声道
    rsp_cfg.dest_rate = 16000; // 目标是 16kHz
    rsp_cfg.dest_ch = 1;       // 目标单声道
    audio_element_handle_t resample = rsp_filter_init(&rsp_cfg);

    // 4. 创建 I2S 写入流
    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_TYLE_AND_CH(CODEC_ADC_I2S_PORT, 16000, 16, AUDIO_STREAM_WRITER, 1);
    i2s_cfg.type = AUDIO_STREAM_WRITER;
    audio_element_handle_t i2s_writer = i2s_stream_init(&i2s_cfg);

    // 5. 设定文件路径
    audio_element_set_uri(fatfs_reader, BAST_PATH "/input.opus");

    // 6. 组装管道
    audio_pipeline_register(pipeline, fatfs_reader, "reader");
    audio_pipeline_register(pipeline, opus_decoder, "decoder");
    audio_pipeline_register(pipeline, resample, "resample");
    audio_pipeline_register(pipeline, i2s_writer, "writer");

    const char *link_tag[4] = {"reader", "decoder", "resample", "writer"};
    audio_pipeline_link(pipeline, link_tag, 4);

    // 7. 启动管道
    ESP_LOGI(TAG, "Starting decoding pipeline");
    audio_pipeline_run(pipeline);

    // 8. 监听事件
    audio_event_iface_handle_t evt;
    audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
    evt = audio_event_iface_init(&evt_cfg);
    audio_pipeline_set_listener(pipeline, evt);

    int volume;
    s_codec_hal->audio_codec_get_volume(&volume);
    ESP_LOGI(TAG, "Current volume: %d", volume);
    s_codec_hal->audio_codec_set_volume(100); // 设置音量为 100%
    ESP_LOGI(TAG, "Set volume to 100%%");
    while (1) {
        audio_event_iface_msg_t msg;
        esp_err_t ret = audio_event_iface_listen(evt, &msg, 100 / portTICK_PERIOD_MS);
        if (msg.source == (void *)opus_decoder && msg.cmd == AEL_MSG_CMD_REPORT_STATUS) {
            audio_element_state_t el_state = audio_element_get_state(opus_decoder);
            if (el_state == AEL_STATE_FINISHED) {
                break;
            }
        }
    }

    // 9. 停止并清理
    audio_pipeline_stop(pipeline);
    audio_pipeline_wait_for_stop(pipeline);
    audio_pipeline_terminate(pipeline);

    audio_pipeline_unregister(pipeline, fatfs_reader);
    audio_pipeline_unregister(pipeline, opus_decoder);
    audio_pipeline_unregister(pipeline, resample);
    audio_pipeline_unregister(pipeline, i2s_writer);

    audio_pipeline_deinit(pipeline);
    audio_element_deinit(fatfs_reader);
    audio_element_deinit(opus_decoder);
    audio_element_deinit(resample);
    audio_element_deinit(i2s_writer);

    ESP_LOGI(TAG, "Opus decoding task finished");
    vTaskDelete(NULL);
}

void mic_to_opus_log_task(void *param) {
    ESP_LOGI(TAG, "MIC -> Opus Log task started");

    // 初始化 audio pipeline
    audio_pipeline_handle_t pipeline;
    audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
    pipeline = audio_pipeline_init(&pipeline_cfg);

    // 初始化 I2S（读取 MIC）
    i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_TYLE_AND_CH(CODEC_ADC_I2S_PORT, 16000, 16, AUDIO_STREAM_READER, 1);
    i2s_cfg.type = AUDIO_STREAM_READER;
    audio_element_handle_t i2s_reader = i2s_stream_init(&i2s_cfg);

    // Opus 编码器
    opus_encoder_cfg_t opus_cfg = DEFAULT_OPUS_ENCODER_CONFIG();
    opus_cfg.bitrate = 16000;
    opus_cfg.complexity = 0;
    opus_cfg.task_core = 1;
    audio_element_handle_t encoder = encoder_opus_init(&opus_cfg);

    // Debug 打印器
    audio_element_handle_t debug = debug_stream_init();

    // 4. 创建 I2S 写入流
    i2s_stream_cfg_t i2s_cfg_write = I2S_STREAM_CFG_DEFAULT_WITH_TYLE_AND_CH(CODEC_ADC_I2S_PORT, 16000, 16, AUDIO_STREAM_WRITER, 1);
    i2s_cfg.type = AUDIO_STREAM_WRITER;
    audio_element_handle_t i2s_writer = i2s_stream_init(&i2s_cfg_write);

    // 注册到管道
    audio_pipeline_register(pipeline, i2s_reader, "i2s_reader");
    audio_pipeline_register(pipeline, encoder, "opus");
    audio_pipeline_register(pipeline, i2s_writer, "i2s_writer");
    audio_pipeline_register(pipeline, debug, "debug");

    const char *link_tag[3] = {"i2s_reader", "opus", "debug"}; // opus写入
    // const char *link_tag[2] = {"i2s_reader", "i2s_writer"}; // 回环
    // const char *link_tag[2] = {"i2s_reader", "debug"}; // pcm写入
    audio_pipeline_link(pipeline, link_tag, 3);

    audio_pipeline_run(pipeline);

    audio_event_iface_handle_t evt = audio_event_iface_init(&(audio_event_iface_cfg_t)AUDIO_EVENT_IFACE_DEFAULT_CFG());
    audio_pipeline_set_listener(pipeline, evt);

    // 无需事件监听，仅等待运行
    while (1) {
        audio_event_iface_msg_t msg;
        if (audio_event_iface_listen(evt, &msg, 500 / portTICK_PERIOD_MS) == ESP_OK) {
            const char *source_tag = audio_element_get_tag((audio_element_handle_t)msg.source);

            if (msg.cmd == AEL_MSG_CMD_REPORT_STATUS) {
                audio_element_state_t state = audio_element_get_state((audio_element_handle_t)msg.source);
                // ESP_LOGW(TAG, "[Event] %s reported status: %d", source_tag, state);
            } else {
                ESP_LOGI(TAG, "[Event] %s cmd: 0x%x", source_tag, msg.cmd);
            }
        }
    }

    audio_pipeline_stop(pipeline);
    audio_pipeline_wait_for_stop(pipeline);
    audio_pipeline_terminate(pipeline);
    audio_pipeline_unregister(pipeline, i2s_reader);
    audio_pipeline_unregister(pipeline, encoder);
    audio_pipeline_unregister(pipeline, debug);
    audio_pipeline_deinit(pipeline);
    audio_element_deinit(i2s_reader);
    audio_element_deinit(encoder);
    audio_element_deinit(debug);

    vTaskDelete(NULL);
}

// 启动 Opus 编码任务
void opus_test(void) {
    xTaskCreatePinnedToCore(mic_to_opus_log_task, "es8388_mic_test", 8192, NULL, tskIDLE_PRIORITY + 1, NULL, 1);

    // xTaskCreatePinnedToCore(opus_to_speaker_task, "opus_to_speaker_task", 8192, NULL, tskIDLE_PRIORITY + 1, NULL, 1);
}